package com.example.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.blog.config.PublisherAware;
import com.example.blog.domain.UserInformation;
import com.example.blog.domain.UuId;
import com.example.blog.domain.Writings;
import com.example.blog.dto.operationalLogs.OperationLogsDto;
import com.example.blog.dto.writing.AdminWritingsUpdateDto;
import com.example.blog.dto.writing.WritingsDelDto;
import com.example.blog.event.publisher.LoggingApplicationEvent;
import com.example.blog.event.publisher.WritingApplicationEvent;
import com.example.blog.mapper.WritingsMapper;
import com.example.blog.service.WritingService;
import com.example.blog.utils.UploadTheFile;
import com.example.blog.vo.writing.WritingDelVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Transactional
public class WritingsServiceImpl extends ServiceImpl<WritingsMapper, Writings> implements WritingService {

    private final UuIdServiceImpl uuIdService;
    private final WritingsMapper writingsMapper;
    private final PublisherAware publisherAware;

    @Autowired
    WritingsServiceImpl(UuIdServiceImpl uuIdService, WritingsMapper writingsMapper, PublisherAware publisherAware) {
        this.writingsMapper = writingsMapper;
        this.uuIdService = uuIdService;
        this.publisherAware = publisherAware;

    }

    //定时任务
    @Override
    public Boolean informationCleanup(List<UserInformation> u_info) throws Exception {
        UploadTheFile uploadTheFile = new UploadTheFile();
        QueryWrapper<Writings> wrapper = new QueryWrapper<>();
        List<Writings> writings = new ArrayList<>();
        List<String> imgSrc = new ArrayList<>();
        try {
            for (UserInformation u : u_info) {
                wrapper.select("image as img").eq("uid", u.getUid());
                writings.addAll(writingsMapper.selectList(wrapper));
            }
            for (Writings writings_ : writings) {
                if (writings_.getImg().contains(",")) {
                    imgSrc.addAll(Arrays.asList(writings_.getImg().split(",")));
                } else imgSrc.add(writings_.getImg());
            }
            String[] fileName = UploadTheFile.intercept(imgSrc.toArray(new String[imgSrc.size()]), "/");
            uploadTheFile.deleteFile(fileName);
            LambdaQueryWrapper<UuId> wrapper_ = new LambdaQueryWrapper<>();
            for (String s : imgSrc) {
                uuIdService.remove(wrapper_.eq(UuId::getUuidValue, s));
            }
            for (UserInformation u : u_info) {
                LambdaQueryWrapper<Writings> wrappers_ = new LambdaQueryWrapper<>();
                writingsMapper.delete(wrappers_.eq(Writings::getUid, u.getUid()));
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("定时清理任务失败");
        }
        return true;
    }

    //上传图片
    @Override
    public List<String> uploadImg(MultipartFile[] file) {
        UploadTheFile uploadTheFile = new UploadTheFile();
        //如果文件长度小于0，或者文件类型不对，返回空
        if (UploadTheFile.fileFormat(file) || file.length < 1)
            return null;
        List<String> keys = uuIdService.randomUUid(file.length);
        //上传图片后，返回地址
        List<String> path = uploadTheFile.uploadFile(file, keys);
        //插入生成的uuid数据存储
        List<UuId> uuIds = new ArrayList<>();
        for (String s : path) {
            UuId uuId = new UuId();
            uuId.setUuidValue(s);
            uuIds.add(uuId);
        }
        uuIdService.saveBatch(uuIds);
        return path;
    }

    //新增文章
    @Override
    public Integer newArticle(MultipartFile[] file, Writings writings) {
        List<String> list = new ArrayList<>();
        Writings writings_ = new Writings();
        writings.setType(writings.getType().replace("，",","));
        BeanUtils.copyProperties(writings, writings_);
        Optional.ofNullable(file)
                .ifPresent(s -> {
                    Stream.of(list).peek(list_ -> {
                        uploadImg(file).stream().map(list_::add).collect(Collectors.toList());
                        writings_.setImg(String.join(",", list_));
                    }).collect(Collectors.toList());
                });
        return writingsMapper.insert(writings_);
    }

    @Override
    public Integer updateArticle(MultipartFile[] file, Writings writings) {
        List<String> originalImg = delImgPath(writings.getImg());//删除标记的图片后,返回需要添加的图片
        List<String> list = new ArrayList<>();
        Optional.ofNullable(file)
                .ifPresent(s -> {
                    Stream.of(list).peek(list_ -> {
                        uploadImg(file).stream().map(list_::add).collect(Collectors.toList());
                    }).collect(Collectors.toList());
                });
        StringBuilder stringBuilder = new StringBuilder();
        if (originalImg.size() > 0) {
            stringBuilder.append(String.join(",", originalImg));
        }
        if (list.size() > 0) {
            if (originalImg.size() > 0) {
                stringBuilder.append(",");
            }
            stringBuilder.append(String.join(",", list));
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        LambdaUpdateWrapper<Writings> wrapper = new LambdaUpdateWrapper<>();
        writings.setType(writings.getType().replace("，",","));
        wrapper.eq(Writings::getWid, writings.getWid()).ne(Writings::getStatus, -1)
                .set(Writings::getDate, sdf.format(new Date()))
                .set(Writings::getBody, writings.getBody())
                .set(Writings::getImg, stringBuilder.toString())
                .set(Writings::getTitle, writings.getTitle())
                .set(Writings::getType,writings.getType())
                .set(Writings::getEncrypt, writings.getEncrypt())
                .set(Writings::getPassword, writings.getPassword());
        return writingsMapper.update(null, wrapper);

    }

    //Admin根据文章Id删除
    @Override
    public WritingDelVo delWritingId(WritingsDelDto writingsDelDto, OperationLogsDto logsVo) {
        WritingDelVo writingDelVo = new WritingDelVo();
        try {
            LambdaQueryWrapper<Writings> wrapper = new LambdaQueryWrapper<>();
            Arrays.stream(writingsDelDto.getWid()).forEach(wid -> {
                wrapper.eq(Writings::getWid, wid);
                writingDelVo.setSuccess(
                        writingsMapper.delete(wrapper) > 0 ? writingDelVo.getSuccess() + 1 : writingDelVo.getSuccess()
                );
            });
            publisherAware.publisher(new WritingApplicationEvent(writingsDelDto));
            publisherAware.publisher(new LoggingApplicationEvent(logsVo));
            logsVo.setOutcome(1);
        } catch (Exception e) {
            logsVo.setOutcome(0);
            publisherAware.publisher(new LoggingApplicationEvent(logsVo));
            throw e;
        }
        return writingDelVo;
    }

    //Admin删除用户所有文章
    @Override
    public Integer writingsAdminDelAll(Long uid, OperationLogsDto logsVo) {
        int remove;
        try {
            LambdaQueryWrapper<Writings> dw = new LambdaQueryWrapper<>();
            LambdaQueryWrapper<Writings> sw = new LambdaQueryWrapper<>();
            List<Writings> writings = writingsMapper.selectList(sw.eq(Writings::getUid, uid).select(Writings::getWid, Writings::getImg));
            if (writings.size() > 0) {
                return 0;
            }
            remove = writingsMapper.delete(dw.eq(Writings::getUid, uid));
            logsVo.setOutcome(1);
            String[] imgList = (writings.stream().map(Writings::getImg).collect(Collectors.toList())).stream().distinct().toArray(String[]::new);
            String[] wid = writings.stream().map(Writings::getWid).toArray(String[]::new);
            Optional.ofNullable(logsVo)
                    .ifPresent(s -> {
                        publisherAware.publisher(new WritingApplicationEvent(new WritingsDelDto(wid, imgList)));
                        publisherAware.publisher(new LoggingApplicationEvent(logsVo));
                    });
        } catch (Exception e) {
            Optional.ofNullable(logsVo)
                    .ifPresent(s -> {
                        logsVo.setOutcome(0);
                        publisherAware.publisher(new LoggingApplicationEvent(logsVo));
                    });
            throw e;
        }
        return remove;
    }

    @Override
    public Integer updateAdminWriting(AdminWritingsUpdateDto writings, OperationLogsDto logsVo) {
        int result;
        try {
            LambdaQueryWrapper<Writings> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Writings::getWid, writings.getWid());
            writings.setType(writings.getType().replaceAll("，", ","));
            Writings writings_ = new Writings();
            BeanUtils.copyProperties(writings, writings_);
            result = writingsMapper.update(writings_, wrapper);
            logsVo.setOutcome(1);
            publisherAware.publisher(new LoggingApplicationEvent(logsVo));
        } catch (Exception exception) {
            logsVo.setOutcome(0);
            publisherAware.publisher(new LoggingApplicationEvent(logsVo));
            throw exception;
        }
        return result;
    }

    //删除标记的图片后,返回需要添加的图片
    public List<String> delImgPath(String path) {
        String[] imgArr = path.split(",");
        List<String> delImg = Arrays.stream(imgArr)
                .filter(s -> s.contains("!del"))
                .map(s -> StringUtils.substringBeforeLast(s, "!del"))
                .collect(Collectors.toList());
        if (delImg.size() > 0) {
            delImg(delImg.toArray(new String[delImg.size()])); //删除需要删除的图片
        }
        return Arrays.stream(imgArr).filter(s -> {
                    return !(s.contains("!del"));
                })
                .collect(Collectors.toList());
    }

    //删除图片
    @Override
    public Integer delImg(String[] oldImg) {
        UploadTheFile uploadTheFile = new UploadTheFile();
        //删除数据库的uuid
        LambdaQueryWrapper<UuId> wrapper = new LambdaQueryWrapper<>();
        for (String s : oldImg) {
            uuIdService.remove(wrapper.eq(UuId::getUuidValue, s));
        }
        //检查传来的文件名是否有‘/’有，则进行截取‘/’后的字符，再进行删除
        String[] fileName = UploadTheFile.intercept(oldImg, "/");
        // 删除oss存储的图片返回删除成功数量
        return uploadTheFile.deleteFile(fileName);
    }

}
